home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / Mac wt 0.04 Folder / MacWT.fat 0.04 / Mac WT source / MacWT.c < prev    next >
Encoding:
Text File  |  1994-05-11  |  10.0 KB  |  515 lines  |  [TEXT/MMCC]

  1. //==================================================================
  2. // MacWT.c                                            <tur 01-May-94>
  3. //
  4. // Mac interface to Chris Laurel's 'wt' demo ["what's that"].
  5. //
  6. //    Comments, Bug Reports/Fixes, etc, to turly@isltd.insignia.com
  7. //
  8. //==================================================================
  9.  
  10. #ifndef    __QUICKDRAW__
  11. #include "LoadMacHeaders.h"
  12. #endif    /* __QUICKDRAW__ */
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16.  
  17. #include "Failure.h"
  18. #include "DirScrnWrite.h"
  19. #include "wt.h"            /* wt */
  20. #include "error.h"
  21. #include "input.h"
  22. #include "framebuf.h"
  23. #include "graphics.h"
  24. #include "MacGame.h"
  25.  
  26.  
  27. /**/
  28.  
  29.  
  30. PixMap            gOffscreenPixMap;
  31. WindowPtr        gWTFTWindow;
  32.  
  33.  
  34. /**/
  35.  
  36.  
  37. static long gStartTicks, gFrameCount;
  38. static Intent gIntent;
  39.  
  40.  
  41. /**/
  42.  
  43.  
  44. void init_input_devices(void)
  45. {
  46.     memset(&gIntent, 0, sizeof(gIntent));
  47. }
  48.  
  49.  
  50. void end_input_devices(void)
  51. {
  52.     // nada for Mac
  53. }
  54.  
  55.  
  56. /**/
  57.  
  58.  
  59. static unsigned CorrectPCRGB(unsigned rgbVal)
  60. {
  61.     register unsigned long    v = rgbVal;
  62.  
  63.     // The PC RGB Values are somewhat low for my liking.
  64.     // This little hack corrects them...
  65.  
  66.     if (v) {
  67.         if (v < 0x0C0C)
  68.             v = 0x0C0C;
  69.         else
  70.         if (v+v < 0xFFFF)
  71.             v += v;
  72.         else
  73.         if (v < 0xEEEE)
  74.             v += 0x1000;
  75.     }
  76.  
  77.     return v;
  78. }
  79.  
  80.  
  81. /**/
  82.  
  83.  
  84. int LoadPaletteFromFile(PaletteHandle pal, const char *palFile)
  85. {
  86.     FILE        *fp;
  87.     int            i, r, g, b;
  88.     RGBColor    col;
  89.     char        name[256];
  90.  
  91.     if (!palFile)
  92.         palFile = DEFAULT_PALETTE_FILE;
  93.  
  94.     fp = fopen(palFile, "rb");
  95.  
  96.     if (fp == NULL) {
  97.         // couldn't open it -- try the ":wt:" subdirectory...
  98.  
  99.         sprintf(name, ":wt:%s", palFile);
  100.         fp = fopen(name, "rb");
  101.         if (fp == NULL)
  102.             Fail("unable to open palette file '%s'", palFile);
  103.     }
  104.  
  105.     col.red = col.green = col.blue = 0xFFFF;    // white, but also transparent!
  106.     SetEntryColor(pal, 0, &col);
  107.  
  108.     for (i = 1; i <= PALETTE_ENTRIES; i++) {
  109.         r = getc(fp);
  110.         g = getc(fp);
  111.         b = getc(fp);
  112.         if (b == EOF)
  113.             Fail("error reading palette file '%s'", palFile);
  114.  
  115.         col.red = (r << 8) | r;
  116.         col.green = (g << 8) | g;
  117.         col.blue = (b << 8) | b;
  118.  
  119.         col.red = CorrectPCRGB(col.red);
  120.         col.green = CorrectPCRGB(col.green);
  121.         col.blue = CorrectPCRGB(col.blue);
  122.  
  123.         SetEntryColor(pal, i, &col);
  124.     }
  125.     fclose(fp);
  126.  
  127.     // set all others (as yet unassigned) to black!
  128.  
  129.     col.red = col.green = col.blue = 0;
  130.     while (i < 255) {
  131.         SetEntryColor(pal, i, &col);
  132.         ++i;
  133.     }
  134.  
  135.     return PALETTE_ENTRIES+2;
  136. }
  137.  
  138.  
  139. /**/
  140.  
  141. // Mac palette indices are PC indices + 1
  142. // due to QuickDraw requirement that white be index 0
  143. // and black index 255 -- PCs are generally the other way round...
  144.  
  145. void MacFixupPixelData(unsigned char *buf, int nBytes)
  146. {
  147.     while (nBytes--) {
  148.         *buf += 1;
  149.         ++buf;
  150.     }
  151. }
  152.  
  153.  
  154. /**/
  155.  
  156.  
  157. void init_graphics(void)
  158. {
  159.  
  160.     // Screen width must be multiple of 4...
  161.  
  162.     FailIf(SCREEN_WIDTH & 3);
  163.  
  164.     if (!gOffscreenPixMap.baseAddr) {
  165.         gOffscreenPixMap.baseAddr = NewPtr(SCREEN_HEIGHT * SCREEN_WIDTH);
  166.         FailNil(gOffscreenPixMap.baseAddr);
  167.     
  168.         gOffscreenPixMap.rowBytes = 0x8000 | SCREEN_WIDTH;
  169.         SetRect(&gOffscreenPixMap.bounds, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  170.     
  171.         gOffscreenPixMap.pixelSize = 8;
  172.         gOffscreenPixMap.cmpCount = 1;
  173.         gOffscreenPixMap.cmpSize = 8;
  174.         gOffscreenPixMap.pmTable = gDirClut;
  175.     }
  176. }
  177.  
  178.  
  179. /**/
  180.  
  181.  
  182. void end_graphics(void)
  183. {
  184. }
  185.  
  186.  
  187. /**/
  188.  
  189.  
  190. static void ShowIfPaused(void)
  191. {
  192.     int    oldFace, oldSize, oldFont, oldMode;
  193.     long tix;
  194.     static int doWhite = true;
  195.     static long    lastFlashTickCount;
  196.  
  197.     if (gPaused) {
  198.  
  199.         oldFace = gWTFTWindow->txFace;
  200.         oldFont = gWTFTWindow->txFont;
  201.         oldSize = gWTFTWindow->txSize;
  202.         oldMode = gWTFTWindow->txMode;
  203.  
  204.         tix = TickCount();
  205.         if (!lastFlashTickCount)
  206.             lastFlashTickCount = tix;
  207.         ForeColor((doWhite) ? whiteColor : blackColor);
  208.         if (tix - lastFlashTickCount > 30) {
  209.             lastFlashTickCount = tix;
  210.             doWhite = !doWhite;
  211.         }
  212.         MoveTo(6, gWTFTWindow->portRect.top + 30);
  213.         TextFont(times);
  214.         TextFace(bold);
  215.         TextSize(24);
  216.         TextMode(srcOr);
  217.  
  218.         DrawString((StringPtr)"\pPaused");
  219.  
  220.         TextSize(12);
  221.         DrawString((StringPtr)"\p - press TAB to continue");
  222.  
  223.         TextSize(oldSize);
  224.         TextFace(oldFace);
  225.         TextFont(oldFont);
  226.         TextMode(oldMode);
  227.  
  228.         ForeColor(blackColor);
  229.     }
  230. }
  231.  
  232.  
  233. /**/
  234.  
  235.  
  236. static void MacAttractMode(void)
  237. {
  238.     int                        oldFont, oldSize, oldFace, oldMode;
  239.  
  240.     FailNil(gWTFTWindow);
  241.  
  242.     // This is a bit of a hack, I’m afraid...
  243.  
  244.     if (!gGameOn) {
  245.         SetPort(gWTFTWindow);
  246.  
  247.         oldFont = gWTFTWindow->txFont;
  248.         oldSize = gWTFTWindow->txSize;
  249.         oldFace = gWTFTWindow->txFace;
  250.         oldMode = gWTFTWindow->txMode;
  251.  
  252.         TextFont(geneva);
  253.         TextSize(9);
  254.         TextMode(srcOr);
  255.  
  256.         MoveTo(4, gWTFTWindow->portRect.bottom - kBottomBorder + 10);
  257.         TextFace(bold);
  258.         DrawString((StringPtr)"\pwt ");
  259.         DrawString(gWTVersion);
  260.         DrawString((StringPtr)"\p - chris laurel’s portable 3D game engine ");
  261. #if    __powerc
  262.         DrawString((StringPtr)"\p(PPC)");
  263. #else
  264.         DrawString((StringPtr)"\p(68K)");
  265. #endif
  266.         MoveTo(4, gWTFTWindow->portRect.bottom - kBottomBorder + 21);
  267.         TextFace(normal);
  268.         DrawString((StringPtr)"\pWorld File — ");
  269.         DrawText(gWorldFileName, 0, strlen(gWorldFileName));
  270.         MoveTo(4, gWTFTWindow->portRect.bottom - kBottomBorder + 32);
  271.         TextFace(italic);
  272.         DrawString((StringPtr)"\pTo change world files, hold down SHIFT while launching MacWT");
  273.  
  274.         TextFont(oldFont);
  275.         TextSize(oldSize);
  276.         TextFace(oldFace);
  277.         TextMode(oldMode);
  278.     }
  279. }
  280.  
  281.  
  282. /**/
  283.  
  284.  
  285. void BeginGame(void)
  286. {
  287.     Rect    r;
  288.  
  289.     FailNil(gWTFTWindow);
  290.     r = gWTFTWindow->portRect;
  291.     r.top = r.bottom - kBottomBorder;
  292.     EraseRect(&r);
  293.  
  294.     gGameOn = true;
  295.     if (gPaused)
  296.         TogglePause();
  297. }
  298.  
  299.  
  300. /**/
  301.  
  302.  
  303. void RefreshWTWindow(void)
  304. {
  305.     PCopyPixFunc    cpF = DirCopyPix;
  306.     long            tNow;
  307.     char            aStr[256];
  308.     int                dirWrite, dubble;
  309.  
  310.     FailNil(gWTFTWindow);
  311.  
  312.     if (gOffscreenPixMap.baseAddr) {
  313.  
  314.         // Dammit, I knew I forgot to extract something from TDirScrn!
  315.         // The following was pointed out by Al Evans (al@crucible.powertools.com)
  316.         // if we can write directly to the screen, set the ctSeed
  317.         // to be the same as the device’s (this is for when we DON’T
  318.         // write directly to the screen, but it does speed up _CopyBits
  319.         // to match my (admittedly C) direct screen write code.
  320.         // Scaling up to 640x400 (from 320x200) is still nearly 2x faster
  321.         // with direct screen writing, though. (As you'd expect, really.)
  322.         // Thanks Al!
  323.  
  324.         dirWrite = CanWriteDirectToScreen(gWTFTWindow);
  325.         if (dirWrite) {
  326.             (**gOffscreenPixMap.pmTable).ctSeed = (**(**(**gTheScreenDevice).gdPMap).pmTable).ctSeed;
  327.         }
  328.  
  329.         dubble = rectWidth(&gWTFTWindow->portRect) >= (SCREEN_WIDTH*2);
  330.         if (dubble)
  331.             cpF = DirCopyPixScaled2;
  332.  
  333.         // We now only bother to use direct screen writes when
  334.         // we're scan-line doubling.
  335.  
  336.         if (dirWrite && !gUseQuickDraw && gGameOn && dubble) {
  337.  
  338.             cpF((long *)gOffscreenPixMap.baseAddr,    /*srcPixels*/
  339.                 SCREEN_WIDTH,                        /*srcRowBytes*/
  340.                 SCREEN_WIDTH,                        /*srcWid*/
  341.                 SCREEN_HEIGHT,                        /*srcHeight*/
  342.                 0, 0,                                /*winStartX/Y*/
  343.                 nil);                                /*pixMungeFunc*/
  344.         }
  345.         else {
  346.             Rect    dstRect;
  347.  
  348.             dstRect = gWTFTWindow->portRect;
  349.              dstRect.bottom -= kBottomBorder;
  350.  
  351.             CopyBits((BitMap *)&gOffscreenPixMap, &gWTFTWindow->portBits,
  352.                     &gOffscreenPixMap.bounds, &dstRect, srcCopy, nil);
  353.  
  354.         }
  355.     }
  356.  
  357.     ShowIfPaused();
  358.  
  359.     MoveTo(4, gWTFTWindow->portRect.bottom - kBottomBorder + 20);
  360.  
  361.     if (gGameOn && gShowFPS) {
  362.         tNow = (TickCount() - gStartTicks) / 60;
  363.         if (!tNow)
  364.             tNow = 1;
  365.  
  366.         aStr[0] = sprintf(aStr+1, "Frame: %ld, fps %ld                ", gFrameCount, ((unsigned long)gFrameCount)/tNow);
  367.         DrawString((StringPtr)aStr);
  368.     }
  369.  
  370. }
  371.  
  372. /**/
  373.  
  374.  
  375. void update_screen(Framebuffer *fb)
  376. {
  377.     RefreshWTWindow();
  378.  
  379.     if (gGameOn) {
  380.         ++gFrameCount;
  381.         if (!gStartTicks)
  382.             gStartTicks = TickCount();
  383.     }
  384. }
  385.  
  386.  
  387. /**/
  388.  
  389.  
  390. Pixel *get_framebuffer_memory(int width, int height)
  391. {
  392.      return (Pixel *)gOffscreenPixMap.baseAddr;
  393. }
  394.  
  395.  
  396. /*****/
  397.  
  398.  
  399. static void add_special(Intent *intent, int special)
  400. {
  401.     if (intent->n_special < MAX_SPECIAL_INTENTIONS) {
  402.         intent->special[intent->n_special] = special;
  403.         intent->n_special++;
  404.     }
  405. }
  406.  
  407.  
  408. /**/
  409.  
  410. #define    MacKeyDown(kmp, code)    ((kmp[code>>3] >> (code & 7)) & 1)
  411.  
  412. Intent *read_input_devices(void)
  413. {
  414.     unsigned char kmp[16];
  415.     Boolean    rotating_cw,
  416.             rotating_ccw,
  417.             moving_forward,
  418.             moving_backward,
  419.             running,
  420.             strafing;
  421.     struct {
  422.         int        rightArrow,
  423.                 leftArrow,
  424.                 upArrow,
  425.                 downArrow,
  426.                 control,
  427.                 escape,
  428.                 shift,
  429.                 slash,
  430.                 space,
  431.                 tabKey;
  432.     } keyboard;
  433.  
  434.  
  435.     gIntent.force_x = gIntent.force_y = gIntent.force_z = 0.0;
  436.     gIntent.force_rotate = 0.0;
  437.     gIntent.n_special = 0;
  438.  
  439.     do {
  440.         GetAndProcessEvent();
  441.  
  442.         GetKeys((long *)kmp);
  443.  
  444.         if (gPaused) {
  445.             gStartTicks = gFrameCount = 0;
  446.             ShowIfPaused();
  447.             init_input_devices();        // zero out the "intent" structure...
  448.         }
  449.  
  450.         if (!gGameOn) {
  451.             // if the forward key is pressed, start the game immediately!
  452.             if (MacKeyDown(kmp, 0x7e) || MacKeyDown(kmp, 0x5b))
  453.                 BeginGame();
  454.             else
  455.                 MacAttractMode();
  456.         }
  457.  
  458.     } while (!gGameOn || (gPaused && !gDone));
  459.  
  460.  
  461.     keyboard.rightArrow = MacKeyDown(kmp, 0x7C) || MacKeyDown(kmp, 0x58);
  462.     keyboard.leftArrow = MacKeyDown(kmp, 0x7b) || MacKeyDown(kmp, 0x56);
  463.     keyboard.upArrow = MacKeyDown(kmp, 0x7e) || MacKeyDown(kmp, 0x5b);
  464.     keyboard.downArrow = MacKeyDown(kmp, 0x7d) || MacKeyDown(kmp, 0x54);
  465.     keyboard.control = MacKeyDown(kmp, 0x3b) || MacKeyDown(kmp, 0x37);    // Ctrl or Cmd
  466.     keyboard.shift = MacKeyDown(kmp, 0x38) || MacKeyDown(kmp, 0x3c);
  467.     keyboard.slash = MacKeyDown(kmp, 0x2c) || MacKeyDown(kmp, 0x4b);
  468.     keyboard.space = MacKeyDown(kmp, 0x31);
  469.     keyboard.tabKey = MacKeyDown(kmp, 0x30);
  470.     keyboard.escape = MacKeyDown(kmp, 0x35) || MacKeyDown(kmp, 0x32);
  471.  
  472.  
  473.     // logic snarfed from the original "x11input.c"
  474.  
  475.     rotating_ccw = keyboard.leftArrow;
  476.     rotating_cw = keyboard.rightArrow;
  477.     moving_forward = keyboard.upArrow;
  478.     moving_backward = keyboard.downArrow;
  479.     running = keyboard.shift;
  480.     strafing = keyboard.slash || keyboard.control;
  481.  
  482.     if (keyboard.space)
  483.         add_special(&gIntent, INTENT_JUMP);
  484.  
  485.     if (gDone)
  486.         add_special(&gIntent, INTENT_END_GAME);
  487.  
  488.  
  489.     if (rotating_cw) {
  490.         if (strafing)
  491.             gIntent.force_y -= 0.5;
  492.         else
  493.             gIntent.force_rotate -= 0.5;
  494.     }
  495.     if (rotating_ccw) {
  496.         if (strafing) {
  497.             gIntent.force_y += 0.5;
  498.         } else
  499.             gIntent.force_rotate += 0.5;
  500.     }
  501.     if (moving_forward)
  502.         gIntent.force_x += 0.5;
  503.     if (moving_backward)
  504.         gIntent.force_x -= 0.5;
  505.     if (running) {
  506.         gIntent.force_x *= 2.0;
  507.         gIntent.force_y *= 2.0;
  508.         gIntent.force_z *= 2.0;
  509.         gIntent.force_rotate *= 2.0;
  510.     }
  511.  
  512.     return &gIntent;
  513. }
  514.  
  515.